#ifndef __I2C_H__
#define __I2C_H__

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "list.h"
#include "lock.h"
#include "wait.h"
#include "log.h"

#include <sys/ioctl.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/types.h>

#define I2C_RDWR  0x0707

struct i2c_msg {
	unsigned short addr;  /* slave address  */
	unsigned short flags;
	unsigned short len;  /* msg length  */
	unsigned char *buf;  /* pointer to msg data  */
};

struct i2c_rdwr_ioctl_data {
	struct i2c_msg  *msgs;  /* pointers to i2c_msgs */
	unsigned int nmsgs;  /* number of i2c_msgs */
};

struct i2c;

enum I2C_EVENT
{
    I2C_EVENT_NONE = 0,
    I2C_EVENT_TEST,
    I2C_EVENT_MAX,
};

typedef int32_t (*i2c_event_notify)(struct i2c*, int32_t, void*, void*);

struct i2c_event_action
{
    i2c_event_notify notify;
    void* object;
    struct i2c_event_action* next;
};

struct i2c_operation
{
    int32_t (*init)(struct i2c*);
    int32_t (*release)(struct i2c*);
    
    int32_t (*open)(struct i2c*, char*);
    int32_t (*close)(struct i2c*);
    
    uint8_t (*read)(struct i2c*, uint8_t, uint16_t, uint16_t*, uint8_t);
    int32_t (*write)(struct i2c*, uint8_t, uint16_t, uint16_t, uint8_t);

    int32_t (*register_notify)(struct i2c*, int32_t, i2c_event_notify notify, void*);
    int32_t (*unregister_notify)(struct i2c*, int32_t, void*);
    int32_t (*trigger_notify)(struct i2c*, int32_t, void*);
};

struct i2c
{
    struct list_head head;
    wait_t wait;
    lock_t lock;
    lock_t notify_lock;

    int running_flag;
    pthread_t pid;
    int opened;
    
    int fd;
    uint8_t slave_dev;

    struct i2c_operation* op;
    struct i2c_event_action *paction[I2C_EVENT_MAX];
};

int32_t create_init_i2c(struct i2c** pi2c);
void release_destroy_i2c(struct i2c* pi2c);
        
#endif
